﻿using System;
using UtilZ.Dotnet.Ex.Cache;

namespace UtilZ.Dotnet.Ex.Json
{
    /// <summary>
    /// json序列化及反序列化类
    /// </summary>
    public class JsonSerializer
    {
        private static readonly ObjectCache _jsonCache = null;
        private static readonly TimeSpan _expire;
        static JsonSerializer()
        {
            //每分钟检查一次数据过期
            _jsonCache = new ObjectCache(60000);
            _expire = TimeSpan.FromMinutes(10);
        }


        private static JsonSerializerCore GetJsonSerializerCore(JsonSerializeSetting setting)
        {
            if (setting == null)
            {
                setting = JsonSerializeSetting.Default;
            }

            object key = setting.GetHashCode();
            JsonSerializerCore jsonSerializerCore = _jsonCache.Get(key) as JsonSerializerCore;
            if (jsonSerializerCore != null)
            {
                return jsonSerializerCore;
            }

            lock (_jsonCache)
            {
                jsonSerializerCore = _jsonCache.Get(key) as JsonSerializerCore;
                if (jsonSerializerCore != null)
                {
                    return jsonSerializerCore;
                }

                jsonSerializerCore = new JsonSerializerCore(setting, _jsonCache, _expire);
                _jsonCache.Set(key, jsonSerializerCore, _expire);
            }

            return jsonSerializerCore;
        }





        /// <summary>
        /// JSON序列化
        /// </summary>
        /// <param name="obj">要序列化的对象</param>
        /// <param name="setting">json序列化设置,为null使用默认值</param>
        /// <returns>json序列化之后的字符串</returns>
        public static string SerializeObject(object obj, JsonSerializeSetting setting = null)
        {
            if (obj == null)
            {
                return JsonConstants.NULL;
            }

            JsonSerializerCore jsonSerializerCore = GetJsonSerializerCore(setting);
            return jsonSerializerCore.Serialize(obj);
        }







        /// <summary>
        /// JSON反序列化
        /// </summary>
        /// <typeparam name="T">反序列化之类的类型</typeparam>
        /// <param name="json">待反序列化的json字符串</param>
        /// <param name="setting">json序列化设置,为null使用默认值</param>
        /// <returns>反序列化之后的对象</returns>
        public static T DeserializeObject<T>(string json, JsonSerializeSetting setting = null)
        {
            object obj = null;
            PrimitiveDeserialize(typeof(T), ref json, ref obj, setting);
            return (T)obj;
        }

        /// <summary>
        /// JSON反序列化
        /// </summary>
        /// <param name="json">待反序列化的json字符串</param>
        /// <param name="targetType">反序列化之类的类型</param>
        /// <param name="setting">json序列化设置,为null使用默认值</param>
        /// <returns>反序列化之后的对象</returns>
        public static object DeserializeObject(string json, Type targetType, JsonSerializeSetting setting = null)
        {
            object obj = null;
            PrimitiveDeserialize(targetType, ref json, ref obj, setting);
            return obj;
        }

        /// <summary>
        /// JSON反序列化-填充到指定对象
        /// </summary>
        /// <param name="json">待反序列化的json字符串</param>
        /// <param name="targetObject">要填充的目标对象</param>
        /// <param name="setting">json序列化设置,为null使用默认值</param>
        /// <returns>反序列化之后的对象</returns>
        public static void PopulateObject(string json, object targetObject, JsonSerializeSetting setting = null)
        {
            PopulateObject(json, ref targetObject, setting);
        }

        /// <summary>
        /// JSON反序列化-填充到指定引用对象
        /// </summary>
        /// <param name="json">待反序列化的json字符串</param>
        /// <param name="targetObject">要填充的目标对象</param>
        /// <param name="setting">json序列化设置,为null使用默认值</param>
        /// <returns>反序列化之后的对象</returns>
        public static void PopulateObject(string json, ref object targetObject, JsonSerializeSetting setting = null)
        {
            if (JsonHelper.OnlyValue(json))
            {
                throw new ArgumentException("json格式必须为对象或集合结构", nameof(json));
            }

            if (targetObject == null)
            {
                throw new ArgumentNullException(nameof(targetObject));
            }

            PrimitiveDeserialize(targetObject.GetType(), ref json, ref targetObject, setting);
        }


        /// <summary>
        /// JSON反序列化-到指定对象
        /// </summary>
        /// <param name="targetType">目标类型</param>
        /// <param name="json">待反序列化的json字符串</param>
        /// <param name="targetObject">要填充的目标对象</param>
        /// <param name="setting">json序列化设置,为null使用默认值</param>
        private static void PrimitiveDeserialize(Type targetType, ref string json, ref object targetObject, JsonSerializeSetting setting = null)
        {
            JsonSerializerCore jsonSerializerCore = GetJsonSerializerCore(setting);
            //jsonSerializerCore.Deserialize(targetType, ref json, ref targetObject);
            jsonSerializerCore.Deserialize(targetType, ref json, ref targetObject);
        }

    }
}
